import javax.swing.JTextArea;
import java.io.OutputStream;
import java.io.IOException;
/***********************************************************************************************
 * Simple implementation of an OutputStream sends its input to a JTextArea.
 * Extensions to this class might look into providing a closing behavior.
 * This class depends on the swing utilities so that it can interoperate with the JTextArea
 * component of a JFrame without going into deadlock.
 *
 * To avoid the paradox of converse logic in the future:
 * Idiom of OutputStream suggests we write bytes to the thing an end user looks at, so
 * the end user can see it.  Considering the notion of InputStream will propogate the
 * paradox.
***********************************************************************************************/
public class GOutputStream extends OutputStream{
	private final JTextArea out;
	private boolean open;
	/***********************************************************************************************
	 * New stream for writing to a JTextArea
	***********************************************************************************************/
	public GOutputStream(JTextArea out)throws IOException{
		this.out=out;
		open=true;
	}
	/***********************************************************************************************
	 * Closes this output stream and releases any system resources associated with this
	 * stream. The general contract of close is that it closes the output stream. A closed stream
	 * cannot perform output operations and cannot be reopened. 
	***********************************************************************************************/
	public void close()throws IOException{
		;//open=false always open
	}//close
	/***********************************************************************************************
	 * Flushes this output stream and forces any buffered output bytes to be written out.
	***********************************************************************************************/
	public void flush()throws IOException{
		;// don't know what to do
	}//flush
	/***********************************************************************************************
	 * Writes b.length bytes from the specified byte array to this output stream.
	***********************************************************************************************/
	public void write(byte[] b)throws IOException{
		try{
			refresh(new String(b));
		}
		catch(Exception e){
			throw new IOException();
		}
	}//write
	/***********************************************************************************************
	 * Writes len bytes from the specified byte array starting at offset off to this output stream.
	 * This method is the one actually used by the progam.
	***********************************************************************************************/
	public void write(byte[] b, int off, int len)throws IOException{
		try{
			refresh(new String(b,off,len));
		}
		catch(Exception e){
			throw new IOException();
		}
	}//write
	/***********************************************************************************************
	 * Writes the specified byte to this output stream.
	***********************************************************************************************/
	public void write(int b)throws IOException{
		try{
			refresh((new Integer(b).toString()));
		}
		catch(Exception e){
			throw new IOException();
		}
	}//write
	/***********************************************************************************************
	 * Internal method to generate an even and send it to the Swing class to actually do the
	 * updating of the JTextArea
	 **********************************************************************************************/
	 public synchronized void refresh(final String s) {
        Runnable  runnable = new Runnable() {
            public void run(){
                out.append(s);
				out.setCaretPosition(out.getText().length());
            }//run
        };
        javax.swing.SwingUtilities.invokeLater(runnable);
    }
}//GOutputStream